package app;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import com.ib.client.*;

public class IBVolatilityProvider implements IVolatilityProvider, EWrapper {
	
    private EClientSocket ibClient = new EClientSocket(this);
    private SimpleDateFormat ibEndTimeFormatter = new SimpleDateFormat("yyyyMMd hh:mm:ss", Locale.ENGLISH);
    private SimpleDateFormat ibDailyTimeFormatter = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH);
    
    private int tickerId = 0;
    private Boolean dataReqComplete = new Boolean(false);
    private String currentEndDateStr;
    private List<SingleIVPoint> currentIVPoints = new ArrayList<SingleIVPoint>();
    
    public IBVolatilityProvider(String host, int port, int clientId) {
    	if (!ibClient.isConnected()) {
    		ibClient.eConnect(host, port, clientId);
    	}
    }
    
	@Override
	public Map<EarningDate, List<SingleIVPoint>> getIVData(Ticker ticker, int daysOut) {
    	Contract ibTicker = new Contract();
    	ibTicker.m_symbol = ticker.symbol;
    	ibTicker.m_exchange = "SMART";
    	ibTicker.m_primaryExch = "ISLAND";
    	ibTicker.m_currency = "USD";
    	ibTicker.m_secType = "STK";
    	Map<EarningDate, List<SingleIVPoint>> ivData = new HashMap<EarningDate, List<SingleIVPoint>>();
    	Date todayDate = new Date();
    	
    	
    	for (EarningDate earningDate : ticker.earningDates) {
    		int diffInDays = (int)( (todayDate.getTime() - earningDate.date.getTime()) / (1000 * 60 * 60 * 24) );
    		if (diffInDays > 300)
    			continue;
    		
    		String endDateTimeStr = ibEndTimeFormatter.format(earningDate.date);
    		this.currentEndDateStr = ibDailyTimeFormatter.format(earningDate.date);
    		String durationStr = daysOut + " D";
    		
    		synchronized (dataReqComplete) {
    			this.currentIVPoints.clear();
    			ibClient.reqHistoricalData(tickerId, ibTicker, endDateTimeStr, durationStr, "1 day", "OPTION_IMPLIED_VOLATILITY", 1, 1);
    			try {
					dataReqComplete.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    			ivData.put(earningDate, new ArrayList<SingleIVPoint>(this.currentIVPoints));
    		}
    		
    		tickerId++;
    	}
    	
		return ivData;
	}

	@Override
	public void error(Exception e) {
		e.printStackTrace();
	}

	@Override
	public void error(String str) {
		System.out.println(str);
	}

	@Override
	public void error(int id, int errorCode, String errorMsg) {
		System.out.println(errorMsg);
	}

	@Override
	public void connectionClosed() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickPrice(int tickerId, int field, double price,
			int canAutoExecute) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickSize(int tickerId, int field, int size) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickOptionComputation(int tickerId, int field,
			double impliedVol, double delta, double optPrice,
			double pvDividend, double gamma, double vega, double theta,
			double undPrice) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickGeneric(int tickerId, int tickType, double value) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickString(int tickerId, int tickType, String value) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickEFP(int tickerId, int tickType, double basisPoints,
			String formattedBasisPoints, double impliedFuture, int holdDays,
			String futureExpiry, double dividendImpact, double dividendsToExpiry) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void orderStatus(int orderId, String status, int filled,
			int remaining, double avgFillPrice, int permId, int parentId,
			double lastFillPrice, int clientId, String whyHeld) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void openOrder(int orderId, Contract contract, Order order,
			OrderState orderState) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void openOrderEnd() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateAccountValue(String key, String value, String currency,
			String accountName) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updatePortfolio(Contract contract, int position,
			double marketPrice, double marketValue, double averageCost,
			double unrealizedPNL, double realizedPNL, String accountName) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateAccountTime(String timeStamp) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void accountDownloadEnd(String accountName) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void nextValidId(int orderId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void contractDetails(int reqId, ContractDetails contractDetails) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void bondContractDetails(int reqId, ContractDetails contractDetails) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void contractDetailsEnd(int reqId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void execDetails(int reqId, Contract contract, Execution execution) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void execDetailsEnd(int reqId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateMktDepth(int tickerId, int position, int operation,
			int side, double price, int size) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateMktDepthL2(int tickerId, int position,
			String marketMaker, int operation, int side, double price, int size) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void updateNewsBulletin(int msgId, int msgType, String message,
			String origExchange) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void managedAccounts(String accountsList) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void receiveFA(int faDataType, String xml) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void historicalData(int reqId, String date, double open,
			double high, double low, double close, int volume, int count,
			double WAP, boolean hasGaps) {
		synchronized(dataReqComplete) {
			if (date.equals(this.currentEndDateStr)) {
				dataReqComplete.notify();
			}
			
			Date optionDate = null;
			try {
				optionDate = ibDailyTimeFormatter.parse(date);
			} catch (ParseException e) {
				e.printStackTrace();
				dataReqComplete.notify();
			}
			
			SingleIVPoint singleIVPoint = new SingleIVPoint(optionDate, open);
			
			if (optionDate != null) {
				this.currentIVPoints.add(singleIVPoint);
			}
		}
	}

	@Override
	public void scannerParameters(String xml) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void scannerData(int reqId, int rank,
			ContractDetails contractDetails, String distance, String benchmark,
			String projection, String legsStr) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void scannerDataEnd(int reqId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void realtimeBar(int reqId, long time, double open, double high,
			double low, double close, long volume, double wap, int count) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void currentTime(long time) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fundamentalData(int reqId, String data) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void deltaNeutralValidation(int reqId, UnderComp underComp) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void tickSnapshotEnd(int reqId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void marketDataType(int reqId, int marketDataType) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void commissionReport(CommissionReport commissionReport) {
		// TODO Auto-generated method stub
		
	}

}
